<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Render函数开发可排序的表格组件</title>
</head>
<body>
    <div id="app">
        <sort-table :config = 'config'></sort-table>
    </div>
    <script src="./utils/vue.js"></script>

    <script>
        Vue.component('sort-table',{
            props:['config'],
            render: function (createElement) {
                if(this.config.columns.length){
                    //加载表格头
                    var _this = this;

                    // 创建表格列样式表
                    var colNodes = this.config.columns.map((item) => {
                        if(item.width){
                            return createElement('col',{style:{width:item.width}});
                        }else{
                            return createElement('col');
                        }
                    });

                    var thNodes = this.config.columns.map((item) => {
                            if(item.sortable){
                                let childStr = item.caption + '↑↓';
                                // item.sortstatus = 'init';
                                return createElement('th',
                                // 节点如何绑定排序事件，并且可以将参数传入handleSort?
                                // 解：使用匿名函数包括起具体的功能函数；参数可以作为功能函数的参数列表传入；
                                    {on:{
                                        click: function()
                                        {
                                            console.log(this.handleSort);
                                            _this.handleSort(item);}
                                        }
                                    },
                                    childStr);
                            }else
                            {
                                return createElement('th',item.caption);
                            }
                        });
                    var thRow = createElement('tr',thNodes);
                    var rows = [];
                    rows = rows.concat(colNodes);
                    rows.push(thRow);

                    //加载行数据
                    var tdRows = [];
                    if(this.config.data.length){
                        tdRows = this.config.data.map((item) => {
                            // Array map function 如果数组里面的数据项不进行映射就不要Return就行；
                            return createElement('tr',Reflect.ownKeys(item).map(key => {
                                //  console.log(key,item[key]);
                                 if(key.toString().indexOf("_")<0){
                                    return createElement('td',item[key]);
                                 }}));
                        });
                    }
                    rows = rows.concat(tdRows);
                    return createElement('table',{attrs:{border:1}},rows);
                }
            },
            methods: {
                // 排序：只考虑单列数据进行排序；
                handleSort: function (col) {
                    if(col.sortstatus == 'init'||col.sortstatus == 'desc')
                    {
                        col.sortstatus = 'asc';
                    }else
                    {
                        col.sortstatus = 'desc';
                    }

                    if(col.sortstatus == 'asc')
                    {
                        this.handleSortByAsc(col);
                    }else if(col.sortstatus == 'desc')
                    {
                        this.handleSortByDesc(col);
                    }
                },
                // 问题：使用某一列数据对数据表进行排序；
                // 冒泡排序后表格视图没有刷新？
                //Vue无法检测到数组：this.config.data[j+1] = temp;这种变化；
                // 和this.config.data.length = 0;
                handleSortByAsc: function (col) {
                    // 冒泡排序
                    // i代表冒泡排序需要确定最大数值的个数；
                    // j代表冒泡排序需要交换的次数；
                    // for(var i = 0;i<this.config.data.length-1;i++){
                    //     for(var j=0;j<this.config.data.length-i-1;j++){
                    //         if(this.config.data[j][col.name]>this.config.data[j+1][col.name])
                    //         {
                    //             let temp = this.config.data[j];
                    //             this.config.data[j] = this.config.data[j+1];
                    //             this.config.data[j+1] = temp;
                    //         }
                    //     }
                    // }
                    if(col.type == 'date'){
                        this.config.data.sort((a,b)=>{
                            let adate = this.convertToDate(a[col.name]);
                            let bdate = this.convertToDate(b[col.name]);
                            if(adate > bdate){
                                return 1;
                            }else if(adate == bdate){
                                return 0;
                            }else{
                                return -1;
                            }
                        });
                    }
                    else{
                        this.config.data.sort((a,b)=>{return a[col.name]-b[col.name];});
                    }
                },
                handleSortByDesc: function (col) {
                    if(col.type == 'date'){
                        this.config.data.sort((a,b)=>{
                            let adate = this.convertToDate(a[col.name]);
                            let bdate = this.convertToDate(b[col.name]);
                            if(adate > bdate){
                                return -1;
                            }else if(adate == bdate){
                                return 0;
                            }else{
                                return 1;
                            }
                        });
                    }
                    else{
                        this.config.data.sort((a,b)=>{return b[col.name]-a[col.name];});
                        }
                },
                convertToDate: function (dateStr) {
                    var dateAr = dateStr.split('-');
                    if(dateAr.length == 3){
                        return new Date(dateAr[0],dateAr[1],dateAr[2]);
                    }else{
                        throw new Error('日期的格式不正确：不是yyyy-mm-dd格式！');
                    }
                }
            }
        });

        var app = new Vue({
            el: '#app',
            data:{
                config: {
                        columns:[
                            {name:'name',caption:'姓名',sortstatus:'init',type:'string',width:"100px"},
                            {name:'age',caption:'年龄',sortable:true,sortstatus:'init',type:'int'},
                            {name:'birthDay',caption:'出生日期',sortable:true,sortstatus:'init',type:'date',width:"100px"},
                            {name:'address',caption:'地址',sortstatus:'init',type:'string',width:"200px"},
                            {name:'sex',caption:'性别',sortstatus:'init',type:'string'}
                        ],
                        data:[
                            {name:'王小明',age:18,birthDay:'1999-02-21',address:'北京市朝阳区芍药居',sex:'男'},
                            {name:'张小刚',age:25,birthDay:'1992-01-23',address:'北京市海淀区西二旗',sex:'男'},
                            {name:'李小红',age:30,birthDay:'1987-11-10',address:'上海市浦东新区世纪大道',sex:'女'},
                            {name:'周小伟',age:26,birthDay:'1991-10-10',address:'深证市南山区深南大道',sex:'男'}
                        ]
                    }
            }
        });
    </script>
</body>
</html>